using System.Diagnostics;
using System.Net.Sockets;

namespace SPI.AgentServer.Services.AI;

/// <summary>
/// SSH隧道服务，自动建立和管理SSH连接
/// </summary>
public class SshTunnelService : IHostedService, IDisposable
{
    private readonly ILogger<SshTunnelService> _logger;
    private readonly IConfiguration _configuration;
    private Process? _sshProcess;
    private bool _isEnabled;
    private readonly string _remoteHost = "188.18.57.151";
    private readonly int _remotePort = 23333;
    private readonly int _localPort = 23333;
    private Timer? _healthCheckTimer;
    private CancellationTokenSource? _healthCheckCts;

    public SshTunnelService(ILogger<SshTunnelService> logger, IConfiguration configuration)
    {
        _logger = logger;
        _configuration = configuration;
        _isEnabled = configuration.GetValue<bool>("Qwen:EnableSshTunnel");
    }

    public async Task StartAsync(CancellationToken cancellationToken)
    {
        if (!_isEnabled)
        {
            _logger.LogInformation("SSH隧道已禁用");
            return;
        }

        try
        {
            // 检查端口是否已经被占用
            if (IsPortInUse(_localPort))
            {
                _logger.LogWarning($"端口 {_localPort} 已被占用，可能SSH隧道已经建立");
                return;
            }

            _logger.LogInformation("正在建立SSH隧道...");
            
            // 启动SSH进程
            var sshPassword = _configuration["Qwen:SshPassword"] ?? "JYDadmin-12345";
            
            // 使用plink（PuTTY的命令行版本）自动输入密码
            var plinkPath = _configuration["Qwen:PlinkPath"] ?? "plink.exe";
            
            if (File.Exists(plinkPath))
            {
                // 使用plink（支持自动密码）
                _sshProcess = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = plinkPath,
                        // 添加保活参数防止SSH隧道空闲超时
                        // -batch: 自动接受主机密钥
                        // -N: 不执行远程命令（仅端口转发）
                        // -T: 禁用伪终端分配
                        // ServerAliveInterval=30: 每30秒发送保活包
                        // ServerAliveCountMax=3: 最多3次保活失败后断开
                        Arguments = $"-batch -N -T -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -L {_localPort}:localhost:{_remotePort} root@{_remoteHost} -pw {sshPassword}",
                        UseShellExecute = false,
                        CreateNoWindow = true,
                        RedirectStandardOutput = true,
                        RedirectStandardError = true
                    }
                };

                // 捕获输出以便调试
                _sshProcess.OutputDataReceived += (sender, e) =>
                {
                    if (!string.IsNullOrEmpty(e.Data))
                    {
                        _logger.LogDebug("SSH Output: {Output}", e.Data);
                    }
                };

                _sshProcess.ErrorDataReceived += (sender, e) =>
                {
                    if (!string.IsNullOrEmpty(e.Data))
                    {
                        _logger.LogWarning("SSH Error: {Error}", e.Data);
                    }
                };
            }
            else
            {
                // 使用标准ssh（需要手动输入密码）
                _sshProcess = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = "ssh",
                        Arguments = $"-o StrictHostKeyChecking=no -L {_localPort}:localhost:{_remotePort} root@{_remoteHost} -N",
                        UseShellExecute = false,
                        CreateNoWindow = true,
                        RedirectStandardOutput = true,
                        RedirectStandardError = true
                    }
                };
                
                _logger.LogWarning("使用ssh命令，可能需要手动输入密码。建议下载plink.exe以支持自动连接");
            }

            _sshProcess.Start();

            // 开始异步读取输出
            if (_sshProcess.StartInfo.RedirectStandardOutput)
            {
                _sshProcess.BeginOutputReadLine();
            }
            if (_sshProcess.StartInfo.RedirectStandardError)
            {
                _sshProcess.BeginErrorReadLine();
            }

            // 等待隧道建立
            await Task.Delay(3000, cancellationToken);
            
            // 检查隧道是否建立成功
            if (IsPortInUse(_localPort))
            {
                _logger.LogInformation("✅ SSH隧道建立成功！");
                
                // 启动健康检查定时器（每60秒检查一次）
                _healthCheckCts = new CancellationTokenSource();
                _healthCheckTimer = new Timer(
                    async _ => await CheckAndRestartTunnelAsync(),
                    null,
                    TimeSpan.FromSeconds(60),
                    TimeSpan.FromSeconds(60)
                );
                _logger.LogInformation("🔍 SSH隧道健康检查已启动（每60秒检查一次）");
            }
            else
            {
                _logger.LogWarning("SSH隧道可能未成功建立，请检查连接");
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "建立SSH隧道失败");
        }
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        try
        {
            // 停止健康检查
            _healthCheckCts?.Cancel();
            _healthCheckTimer?.Dispose();
            
            if (_sshProcess != null && !_sshProcess.HasExited)
            {
                _sshProcess.Kill();
                _sshProcess.Dispose();
                _logger.LogInformation("SSH隧道已关闭");
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "关闭SSH隧道时出错");
        }

        return Task.CompletedTask;
    }

    private bool IsPortInUse(int port)
    {
        try
        {
            using var client = new TcpClient();
            var result = client.BeginConnect("localhost", port, null, null);
            var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromMilliseconds(500));
            if (success)
            {
                client.EndConnect(result);
                return true;
            }
            return false;
        }
        catch
        {
            return false;
        }
    }

    public void Dispose()
    {
        _healthCheckCts?.Cancel();
        _healthCheckCts?.Dispose();
        _healthCheckTimer?.Dispose();
        _sshProcess?.Dispose();
    }

    /// <summary>
    /// 检查SSH隧道健康状态，如果断开则自动重启
    /// </summary>
    private async Task CheckAndRestartTunnelAsync()
    {
        if (!_isEnabled)
            return;

        try
        {
            // 检查SSH进程是否还在运行
            if (_sshProcess == null || _sshProcess.HasExited)
            {
                _logger.LogWarning("⚠️ SSH隧道进程已退出，正在重启...");
                await RestartTunnelAsync();
                return;
            }

            // 检查端口是否仍然可用
            if (!IsPortInUse(_localPort))
            {
                _logger.LogWarning("⚠️ SSH隧道端口不可用，正在重启...");
                await RestartTunnelAsync();
                return;
            }

            _logger.LogDebug("✅ SSH隧道健康检查通过");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "SSH隧道健康检查失败");
        }
    }

    /// <summary>
    /// 重启SSH隧道
    /// </summary>
    private async Task RestartTunnelAsync()
    {
        try
        {
            // 先停止现有进程
            if (_sshProcess != null && !_sshProcess.HasExited)
            {
                _sshProcess.Kill();
                _sshProcess.Dispose();
                _sshProcess = null;
            }

            // 等待一小段时间
            await Task.Delay(2000);

            // 重新启动隧道
            await StartAsync(CancellationToken.None);
            
            _logger.LogInformation("✅ SSH隧道已成功重启");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "重启SSH隧道失败");
        }
    }
}













